/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		acleditor init class
 * PURPOSE:		acl editor dialog class initialization
 *				included as part of acleditor.cpp
 */

PCWSTR AceTypeLabels[] = 
{
	L"Allow",
	L"Deny",
	L"Audit",
	L"Alarm",
	L"Allow Compound",
	L"Allow Obj",
	L"Deny Obj",
	L"Audit Obj",
	L"Alarm Obj",
	L"Allow Cb",
	L"Deny Cb",
	L"Allow Cb Obj",
	L"Deny Cb Obj",
	L"Audit Cb",
	L"Alarm Cb",
	L"Audit Cb Obj",
	L"Alarm Cb Obj",
	L"Integrity Label"
};

PCWSTR LabelHeaders[DESC_SPECIFIC_SIZE] = 
{
	L"Deny write lower",
	L"Deny read lower",
	L"Deny execute lower"
};

static const UCHAR ACE_TYPE_MAX_STD = ACCESS_MAX_MS_V2_ACE_TYPE;
static const UCHAR ACE_TYPE_MAX_OBJ = ACCESS_MAX_MS_OBJECT_ACE_TYPE;
static const UCHAR ACE_TYPE_MAX = 0x11;// ACCESS_MAX_MS_V5_ACE_TYPE;

UCHAR GetAceTypeIndex(PWSTR Name)
{
	for(UCHAR i = 0; i <= ACE_TYPE_MAX; i++)
		if(_wcsicmp(AceTypeLabels[i], Name) == 0)
			return i;

	return static_cast<UCHAR>(_wtoi(Name));
}

void AddAceTypeToMenu(HMENU Menu, UCHAR Index, UINT ExtraFlags)
{
	RaiseOnWin32ErrorT(AppendMenu(Menu, MF_STRING | ExtraFlags, Index + 1, AceTypeLabels[Index])); //Index+1 for menu id because 0 means no selection
}

void InitDefaultColumnDescriptions()
{
	RtlZeroMemory(DefaultColumnDescriptions, sizeof(WCHAR) * COL_MAX);

	//note that columns are numbered by offset in big-endian order, opposite of the labels and winnt.h
	
	DefaultColumnDescriptions[COL_TSTE_NAME] = L"Trustee Name";
	DefaultColumnDescriptions[COL_TSTE_SID] = L"Trustee Sid";
	DefaultColumnDescriptions[COL_OBJ_TYPE] = L"Object Type";
	DefaultColumnDescriptions[COL_OBJ_INH_TYPE] = L"Inh. Object Type";
	DefaultColumnDescriptions[COL_INH_SOURCE] = L"Inh. Source";
	DefaultColumnDescriptions[COL_ACE_TYPE] = L"ACE Type";
	
	DefaultColumnDescriptions[COL_ACE_FLAGS + 0] = L"Object Inherit";
	DefaultColumnDescriptions[COL_ACE_FLAGS + 1] = L"Container Inherit";
	DefaultColumnDescriptions[COL_ACE_FLAGS + 2] = L"No Propogate";
	DefaultColumnDescriptions[COL_ACE_FLAGS + 3] = L"Inherit Only";
	DefaultColumnDescriptions[COL_ACE_FLAGS + 4] = L"Inherited";
	DefaultColumnDescriptions[COL_ACE_FLAGS + 5] = L"ACE Flag Bit 5";
	DefaultColumnDescriptions[COL_ACE_FLAGS + 6] = L"Audit Success";
	DefaultColumnDescriptions[COL_ACE_FLAGS + 7] = L"Audit Failure";

	DefaultColumnDescriptions[COL_GENERIC + 0] = L"Generic All";
	DefaultColumnDescriptions[COL_GENERIC + 1] = L"Generic Execute";
	DefaultColumnDescriptions[COL_GENERIC + 2] = L"Generic Write";
	DefaultColumnDescriptions[COL_GENERIC + 3] = L"Generic Read";

	DefaultColumnDescriptions[COL_STANDARD + 0] = L"Delete";
	DefaultColumnDescriptions[COL_STANDARD + 1] = L"Read Control";
	DefaultColumnDescriptions[COL_STANDARD + 2] = L"Write DACL";
	DefaultColumnDescriptions[COL_STANDARD + 3] = L"Write Owner";
	DefaultColumnDescriptions[COL_STANDARD + 4] = L"Synchronize";
	DefaultColumnDescriptions[COL_STANDARD + 5] = L"Standard Bit 5";
	DefaultColumnDescriptions[COL_STANDARD + 6] = L"Standard Bit 6";
	DefaultColumnDescriptions[COL_STANDARD + 7] = L"Standard Bit 7";

	DefaultColumnDescriptions[COL_SYSTEM] = L"System Access"; //standard + 7
	DefaultColumnDescriptions[COL_MAX_ALLOWED] = L"Maximum Allowed"; //standard + 8

	DefaultColumnDescriptions[COL_RESERVE + 0] = L"Reserved Bit A";
	DefaultColumnDescriptions[COL_RESERVE + 1] = L"Reserved Bit B";

	DefaultColumnDescriptions[COL_SPECIFIC + 0] = L"Specific Bit 0";
	DefaultColumnDescriptions[COL_SPECIFIC + 1] = L"Specific Bit 1";
	DefaultColumnDescriptions[COL_SPECIFIC + 2] = L"Specific Bit 2";
	DefaultColumnDescriptions[COL_SPECIFIC + 3] = L"Specific Bit 3";
	DefaultColumnDescriptions[COL_SPECIFIC + 4] = L"Specific Bit 4";
	DefaultColumnDescriptions[COL_SPECIFIC + 5] = L"Specific Bit 5";
	DefaultColumnDescriptions[COL_SPECIFIC + 6] = L"Specific Bit 6";
	DefaultColumnDescriptions[COL_SPECIFIC + 7] = L"Specific Bit 7";
	DefaultColumnDescriptions[COL_SPECIFIC + 8] = L"Specific Bit 8";
	DefaultColumnDescriptions[COL_SPECIFIC + 9] = L"Specific Bit 9";
	DefaultColumnDescriptions[COL_SPECIFIC + 10] = L"Specific Bit A";
	DefaultColumnDescriptions[COL_SPECIFIC + 11] = L"Specific Bit B";
	DefaultColumnDescriptions[COL_SPECIFIC + 12] = L"Specific Bit C";
	DefaultColumnDescriptions[COL_SPECIFIC + 13] = L"Specific Bit D";
	DefaultColumnDescriptions[COL_SPECIFIC + 14] = L"Specific Bit E";
	DefaultColumnDescriptions[COL_SPECIFIC + 15] = L"Specific Bit F";
}

int const ToolSepWidth = 8;

TBBUTTON ToolButtons[] = 
{
	{TbOk, TbOk, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Ok (Exit returning changes) <CTRL+K>"), 0},
	{TbCancel, TbCancel, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Cancel (Exit, discard changes) <Esc>"), 0},
	{TbReturnNull, TbReturnNull, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Return NULL (grants full access to absolutely everyone in a DACL, same as empty in a SACL) <CTRL+N>"), 0},
	{TbReturnUnspecified, TbReturnUnspecified, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Return unspecified (Exit, have SD edit forget about this ACL's state)<CTRL+?>"), 0},
	{TbApply, TbApply, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Apply (Return changes without closing) <CTRL+A>"), 0},

	{ToolSepWidth, 0, 0, TBSTYLE_SEP, {}, 0, 0},
	{TbShowSid, TbShowSid, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show trustee SIDs <SHIFT+1>"), 0},
	{TbShowObject, TbShowObject, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show object types <SHIFT+2>"), 0},
	{TbShowObjectInherit, TbShowObjectInherit, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show inheritable object types <SHIFT+3>"), 0},
	{TbShowInheritSource, TbShowInheritSource, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show source of inherited ACEs <SHIFT+4>"), 0},
	{TbShowSpecific, TbShowSpecific, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show access mask bits specific to this object type <SHIFT+5>"), 0},
	{TbShowStandard, TbShowStandard, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show access mask bits standard to all object types <SHIFT+6>"), 0},
	{TbShowGeneric, TbShowGeneric, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show generic access mask bits that apply to any object type <SHIFT+7>"), 0},
	{TbShowExtra, TbShowExtra, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Show extras (things undefined and most likely unused) <SHIFT+0>"), 0},

	{ToolSepWidth, 0, 0, TBSTYLE_SEP, {}, 0, 0},
	{TbInsertBefore, TbInsertBefore, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Insert a new ACE above selection <CTRL+PgUp>"), 0},
	{TbInsertAfter, TbInsertAfter, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Insert a new ACE below selection <CTRL+PgDown>"), 0},
	{TbShiftUp, TbShiftUp, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Shift selected ACE up <CTRL+Up>"), 0},
	{TbShiftDown, TbShiftDown, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Shift selectied ACE down <CTRL+Down>"), 0},
	{TbDelete, TbDelete, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Delete selected ACE <Delete>"), 0},
	{TbClear, TbClear, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Clear all ACEs <CTRL+Delete>"), 0},

	{ToolSepWidth, 0, 0, TBSTYLE_SEP, {}, 0, 0},
	{TbDefaulted, TbDefaulted, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"ACL defaulted <CTRL+D>"), 0},
	{TbProtected, TbProtected, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"ACL protected from auto-inheritance <CTRL+P>"), 0},
	{TbAutoInherit, TbAutoInherit, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"ACL auto-inheritance <CTRL+I>"), 0},
	{TbUntrusted, TbUntrusted, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"ACL untrusted <CTRL+U>"), 0},
	{TbReinherit, TbReinherit, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Recaluclate inherited ACEs, according to merge mode <CTRL+R>"), 0},
	{TbLoadDefault, TbLoadDefault, TBSTATE_ENABLED, TBSTYLE_BUTTON, {}, c_cast<INT_PTR>(L"Load default ACE <CTRL+E>"), 0},
	{TbMergeUnprotect, TbMergeUnprotect, TBSTATE_ENABLED, TBSTYLE_CHECK, {}, c_cast<INT_PTR>(L"Override protected flag on children when merging for auto-inheritance <CTRL+O>"), 0},

	{ToolSepWidth, 0, 0, TBSTYLE_SEP, {}, 0, 0},
	{TbMergeNone, TbMergeNone, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {}, c_cast<INT_PTR>(L"Do not modify children <CTRL+0>"), 0},
	{TbMergeInhNone, TbMergeInhNone, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {}, c_cast<INT_PTR>(L"No inheritance (children's ACLs will have no inherited entries) <CTRL+1>"), 0},
	{TbMergeInhOnly, TbMergeInhOnly, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {}, c_cast<INT_PTR>(L"Inherited entries only (children's ACL contents replaced by inherited entries) <CTRL+2>"), 0},
	{TbMergeInhLast, TbMergeInhLast, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {}, c_cast<INT_PTR>(L"Inherited entries after direct entries <CTRL+3>"), 0},
	{TbMergeInhFirst, TbMergeInhFirst, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {}, c_cast<INT_PTR>(L"Inherited entries before direct entries <CTRL+4>"), 0},
	{TbMergeDenyFirst, TbMergeDenyFirst, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {}, c_cast<INT_PTR>(L"Deny entries first <CTRL+5>"), 0},
};

ACCEL AccelEntries[] =
{
	{FVIRTKEY, VK_RETURN, ID_EDIT_ROW},
	{FVIRTKEY | FCONTROL, 'K', TbOk},
	{FVIRTKEY, VK_ESCAPE, TbCancel},
	{FVIRTKEY | FCONTROL, 'N', TbReturnNull},
	{FVIRTKEY | FCONTROL | FSHIFT, VK_OEM_2, TbReturnUnspecified},
	{FVIRTKEY | FCONTROL, 'A', TbApply},
	{FVIRTKEY | FSHIFT, '1', TbShowSid},
	{FVIRTKEY | FSHIFT, '2', TbShowObject},
	{FVIRTKEY | FSHIFT, '3', TbShowObjectInherit},
	{FVIRTKEY | FSHIFT, '4', TbShowInheritSource},
	{FVIRTKEY | FSHIFT, '5', TbShowSpecific},
	{FVIRTKEY | FSHIFT, '6', TbShowStandard},
	{FVIRTKEY | FSHIFT, '7', TbShowGeneric},
	{FVIRTKEY | FSHIFT, '0', TbShowExtra},
	{FVIRTKEY | FCONTROL, VK_PRIOR, TbInsertBefore},
	{FVIRTKEY | FCONTROL, VK_NEXT, TbInsertAfter},
	{FVIRTKEY | FCONTROL, VK_UP, TbShiftUp},
	{FVIRTKEY | FCONTROL, VK_DOWN, TbShiftDown},
	{FVIRTKEY, VK_DELETE, TbDelete},
	{FVIRTKEY | FCONTROL, VK_DELETE, TbClear},
	{FVIRTKEY | FCONTROL, 'D', TbDefaulted},
	{FVIRTKEY | FCONTROL, 'P', TbProtected},
	{FVIRTKEY | FCONTROL, 'I', TbAutoInherit},
	{FVIRTKEY | FCONTROL, 'U', TbUntrusted},
	{FVIRTKEY | FCONTROL, 'R', TbReinherit},
	{FVIRTKEY | FCONTROL, 'E', TbLoadDefault},
	{FVIRTKEY | FCONTROL, 'O', TbMergeUnprotect},
	{FVIRTKEY | FCONTROL, '0', TbMergeNone},
	{FVIRTKEY | FCONTROL, '1', TbMergeInhNone},
	{FVIRTKEY | FCONTROL, '2', TbMergeInhOnly},
	{FVIRTKEY | FCONTROL, '3', TbMergeInhLast},
	{FVIRTKEY | FCONTROL, '4', TbMergeInhFirst},
	{FVIRTKEY | FCONTROL, '5', TbMergeDenyFirst}
};

static PCWSTR ClassName = L"SdEdAclEditor";

ATOM ClassAtom;

struct WindowClassLifetime
{
	TopLabel::WindowClassLifetime TopLabelClass;

	WindowClassLifetime()
	{
		WNDCLASS Class;

		RtlZeroStruct(Class);

		Class.hInstance = SdEditGModule;
		Class.hCursor = LoadCursor(SdEditGModule, IDC_ARROW);
		Class.lpfnWndProc = &ClassedWindowBase::ClassedWndProc;
		Class.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
		Class.lpszClassName = ClassName;
		Class.hIcon = LoadIcon(SdEditGModule, MAKEINTRESOURCE(IDI_ACLEDITOR));

		ClassAtom = RegisterClass(&Class);

		RaiseOnWin32ErrorT(ClassAtom != NULL);

		MenuAceTypeStd = CreatePopupMenu();
		{
			AddAceTypeToMenu(MenuAceTypeStd, ACCESS_ALLOWED_ACE_TYPE, 0); 
			AddAceTypeToMenu(MenuAceTypeStd, ACCESS_DENIED_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeStd, SYSTEM_AUDIT_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeStd, SYSTEM_ALARM_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeStd, SYSTEM_MANDATORY_LABEL_ACE_TYPE, 0);
		}

		MenuAceTypeObj = CreatePopupMenu();
		{
			AddAceTypeToMenu(MenuAceTypeObj, ACCESS_ALLOWED_ACE_TYPE, 0); 
			AddAceTypeToMenu(MenuAceTypeObj, ACCESS_DENIED_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeObj, SYSTEM_AUDIT_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeObj, SYSTEM_ALARM_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeObj, ACCESS_ALLOWED_OBJECT_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeObj, ACCESS_DENIED_OBJECT_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeObj, SYSTEM_AUDIT_OBJECT_ACE_TYPE, 0);
			AddAceTypeToMenu(MenuAceTypeObj, SYSTEM_ALARM_OBJECT_ACE_TYPE, 0);
		}

		MenuAceTypeEx = CreatePopupMenu();

		for(UCHAR i = 0; i <= ACE_TYPE_MAX; i++)
			AddAceTypeToMenu(MenuAceTypeEx, i, (i == 4 ? MF_GRAYED : 0));

		Accelerator = RaiseOnWin32ErrorT(CreateAcceleratorTableA(AccelEntries, sizeof(AccelEntries) / sizeof *AccelEntries));
	}

	~WindowClassLifetime()
	{
		UnregisterClass(ClassName, SdEditGModule);
	}
};